using System;
using System.Collections.Generic;
using DecisionMaking.BusinessLogic.Model;
using NHibernate.Exceptions;
using NHibernate;
using DecisionMaking.Domain;
using Castle.Services.Transaction;
namespace DecisionMaking.BusinessLogic.Impl
{
	[Transactional]
	public class EnvironmentManager : IEnvironmentManager
	{
		public IAccountManager AccountManager {get; set;}
		
		#region Environments
		[Transaction(Castle.Services.Transaction.TransactionMode.NotSupported)]
		public Domain.Environment GetEnvironment (int environmentId)
		{
			try
			{
				return Domain.Environment.Find(environmentId);
			}
			catch (ObjectNotFoundException e)
			{
				throw new EntityNotFoundException(typeof(Domain.Environment), environmentId, e);
			}
		}
		
		[Transaction(Castle.Services.Transaction.TransactionMode.NotSupported)]
		public IList<Domain.Environment> GetEnvironments (int accountId)
		{
			return Domain.Environment.FindByAccountId(accountId);
		}			
				
		public DecisionMaking.Domain.Environment SaveEnvironment (EnvironmentModel model)
		{
			DecisionMaking.Domain.Environment environment;
			
			if (model.Id == null)
			{
				// new environment, assign account from model
				environment = new DecisionMaking.Domain.Environment();
				environment.Account = AccountManager.GetAccount(model.AccountId.Value);
				
				// TODO create 3 default cue attributes
			}
			else
			{
				// existing environment, load and make sure account from model is the owner
				environment = GetEnvironment(model.Id.Value);
				if (environment.Account.Id != model.AccountId)
				{
					throw new AccessDeniedException(model.AccountId.Value, typeof(Domain.Environment), model.Id.Value);
				}				
			}
			
		    try 
		    {
				environment.Name = model.Name;
				environment.Description = model.Description;
				environment.IndependentVariableName = model.IndependentVariable;
				environment.Settings.IsPublic = model.IsPublic;
				
				environment.SaveAndFlush();
				
				return environment;
			}
			catch (ConstraintViolationException e) 
			{
				if (e.ConstraintName == "uix_environment_name") 
				{
					throw new DuplicateEnvironmentNameException(model.Name, e);
				}
				else 
				{
					throw; // unexpected exception, throw to caller
				}
			}
					
		}
		#endregion Environments
		
		#region CueAttributes
		[Transaction(Castle.Services.Transaction.TransactionMode.NotSupported)]
		public IList<CueAttribute> GetCueAttributes (int environmentId)
		{
			return CueAttribute.FindByEnvironmentId(environmentId);
		}		
		
		public CueAttribute AddCueAttribute (CueAttributeModel model)
		{
			try
			{
				CueAttribute attribute = new CueAttribute
				{
					Environment = GetEnvironment(model.EnvironmentId),
					Name = model.Name
				};
				
				attribute.SaveAndFlush();
				
				return attribute;
			}
			catch (ConstraintViolationException e) 
			{
				if (e.ConstraintName == "uix_cue_attribute_name") 
				{
					throw new DuplicateCueAttributeNameException(model.Name, e);
				}
				else 
				{
					throw; // unexpected exception, throw to caller
				}
			}			
			
		}

		public void RemoveCueAttribute (int id)
		{
			CueAttribute.Find(id).Delete();
		}

		#endregion CueAttributes
		
		#region Cues
		[Transaction(Castle.Services.Transaction.TransactionMode.NotSupported)]
		public IList<Cue> GetCues (int environmentId)
		{
			return Cue.FindByEnvironmentId(environmentId);
		}

		public Cue AddCue (CueModel model)
		{
			throw new NotImplementedException ();
		}

		public void RemoveCue (int id)
		{
			throw new NotImplementedException ();
		}
		#endregion Cues

		public void SaveCandidates (int environmentId, IList<Domain.Candidate> candidates)
		{
			throw new NotImplementedException ();
		}

		public void GenerateAgents (int environmentId, int amount)
		{
			throw new NotImplementedException ();
		}


		public IList<Domain.Candidate> GetCandidates (int environmentId)
		{
			throw new NotImplementedException ();
		}
	
	}
}

